import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Input, Select } from 'antd';
import React, { useCallback, useMemo, useState } from 'react';
import { useContextSelector } from 'use-context-selector';

import QuestionTip from '@/components/tooltip/QuestionTip';
import { useConfirm } from '@/hooks/use-confirm';
import { t } from '@/locales/i18n';
import { WorkflowContext } from '@/pages/app/detail/components/Workflow/context';
import {
  FlowNodeInputTypeEnum,
  FlowNodeTypeEnum,
  FlowValueTypeMap,
  VARIABLE_NODE_ID,
  WorkflowIOValueTypeEnum,
} from '@/types/workflow/constant';
import { FlowNodeInputItemType, ReferenceValueProps } from '@/types/workflow/io';
import { isWorkflowStartOutput } from '@/types/workflow/template/system/workflowStart';
import { getInputComponentProps } from '@/utils/workflow/node/io/utils';

import { defaultInput } from '../../FieldEditModal';
import { ReferSelector, useReference } from '../Reference';

import type { RenderInputProps } from '../../type';

const { TextArea } = Input;

const DynamicInputs = (props: RenderInputProps) => {
  const { item, inputs = [], nodeId } = props;
  const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);

  const dynamicInputs = useMemo(() => inputs.filter((item) => item.canEdit), [inputs]);
  const keys = useMemo(() => {
    return inputs.map((input) => input.key);
  }, [inputs]);

  const [editField, setEditField] = useState<FlowNodeInputItemType>();

  const onAddField = useCallback(
    ({ data }: { data: FlowNodeInputItemType }) => {
      const newInput: FlowNodeInputItemType = {
        ...data,
        required: true,
      };

      onChangeNode({
        nodeId,
        type: 'addInput',
        value: newInput,
      });
    },
    [nodeId, onChangeNode],
  );

  const Render = useMemo(() => {
    return (
      <div className="border-b-2 border-line-2 pb-2">
        <div className="nodrag relative flex cursor-pointer">
          <div className="text-md relative flex space-x-1">
            <div>{item.label || t('custom_input')}</div>
            {item.description && <QuestionTip title={t(item.description as any)} icon="" />}
          </div>
          <div className="flex-1" />
        </div>
        {/* field render */}
        <div className="mt-2">
          {dynamicInputs.map((children, index) => (
            <div
              className={`${index !== dynamicInputs.length - 1 ? 'mb-3' : ''}`}
              key={children.key}
            >
              <Reference {...props} inputChildren={children} />
            </div>
          ))}
        </div>
        <div className="flex w-full items-center justify-center">
          <Button
            type="text"
            className="mt-2"
            icon={<PlusOutlined />}
            onClick={() => {
              onAddField({
                data: {
                  ...defaultInput,
                  ...getInputComponentProps(item),
                },
              });
            }}
          >
            添加变量
          </Button>
        </div>
      </div>
    );
  }, [dynamicInputs, item, onAddField, props]);

  return Render;
};

export default React.memo(DynamicInputs);

function Reference({
  inputChildren,
  ...props
}: RenderInputProps & {
  inputChildren: FlowNodeInputItemType;
}) {
  const { nodeId, inputs = [], item } = props;
  const { ConfirmModal, openConfirm } = useConfirm({
    type: 'delete',
    content: t('confirm_delete_field_tip'),
  });
  const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
  const nodeList = useContextSelector(WorkflowContext, (v) => v.nodeList);

  const keys = useMemo(() => {
    return inputs.map((input) => input.key);
  }, [inputs]);
  const [editField, setEditField] = useState<FlowNodeInputItemType>();
  const [data, setData] = useState<FlowNodeInputItemType>(inputChildren);

  const { customInputConfig } = item;

  const inputType = FlowNodeInputTypeEnum.reference;

  const showValueTypeSelect = useMemo(() => {
    if (
      !customInputConfig?.selectValueTypeList ||
      customInputConfig?.selectValueTypeList.length <= 1
    )
      return false;
    if (inputType === FlowNodeInputTypeEnum.reference) return true;

    return false;
  }, [customInputConfig?.selectValueTypeList, inputType]);

  const valueTypeSelectList = useMemo(() => {
    if (!customInputConfig?.selectValueTypeList) return [];

    const dataTypeSelectList = Object.values(FlowValueTypeMap).map((item) => ({
      label: t(item.label as any),
      value: item.value,
    }));

    return dataTypeSelectList.filter((item) =>
      customInputConfig?.selectValueTypeList?.includes(item.value),
    );
  }, [customInputConfig?.selectValueTypeList]);

  const onSelect = useCallback(
    (e: ReferenceValueProps) => {
      const workflowStartNode = nodeList.find(
        (node) => node.flowNodeType === FlowNodeTypeEnum.workflowStart,
      );

      const newValue =
        e && e[0] === workflowStartNode?.id && !isWorkflowStartOutput(e[1])
          ? [VARIABLE_NODE_ID, e[1]]
          : e;

      onChangeNode({
        nodeId,
        type: 'replaceInput',
        key: inputChildren.key,
        value: {
          ...inputChildren,
          value: newValue,
        },
      });
    },
    [inputChildren, nodeId, nodeList, onChangeNode],
  );

  const { referenceList, formatValue } = useReference({
    nodeId,
    valueType: inputChildren.valueType,
    value: inputChildren.value,
  });

  const onUpdateField = useCallback(
    ({ data }: { data: FlowNodeInputItemType }) => {
      if (!data.key) return;

      onChangeNode({
        nodeId,
        type: 'replaceInput',
        key: inputChildren.key,
        value: data,
      });
    },
    [inputChildren.key, nodeId, onChangeNode],
  );
  const onDel = useCallback(() => {
    onChangeNode({
      nodeId,
      type: 'delInput',
      key: inputChildren.key,
    });
  }, [inputChildren.key, nodeId, onChangeNode]);

  return (
    <>
      <div className="mb-1 flex w-full items-center gap-1">
        <div className="flex flex-1 flex-col gap-1">
          <div className="flex w-full">
            <div className="flex w-full space-x-3">
              {/* key */}
              <Input
                className="workflow-input ml-2 bg-gray-100"
                bordered={false}
                placeholder={t('Variable_name')}
                value={data.key}
                onBlur={() => {
                  onUpdateField({
                    data: {
                      ...data,
                      key: data.key,
                      label: data.key,
                    },
                  });
                }}
                onChange={(e) => {
                  setData({
                    ...data,
                    key: e.target.value,
                  });
                }}
              />
              {showValueTypeSelect && (
                <Select
                  className="workflow-select w-full"
                  popupClassName="workflow-dropdown"
                  placeholder={t('core.module.Data Type')}
                  options={valueTypeSelectList.filter(
                    (item) => item.value !== WorkflowIOValueTypeEnum.arrayAny,
                  )}
                  value={data.valueType}
                  onChange={(e) => {
                    setData({
                      ...data,
                      valueType: e as WorkflowIOValueTypeEnum,
                    });
                    onUpdateField({
                      data: {
                        ...data,
                        valueType: e as WorkflowIOValueTypeEnum,
                      },
                    });
                  }}
                />
              )}
            </div>
          </div>
          <ReferSelector
            placeholder={t(
              (inputChildren.referencePlaceholder as any) || 'select_reference_variable',
            )}
            list={referenceList}
            value={formatValue}
            onSelect={onSelect}
          />
          {customInputConfig?.showDescription && (
            <div className="w-full">
              <TextArea
                className="text-gray-500"
                placeholder={t('input_description')}
                value={data.description}
                onBlur={() => {
                  onUpdateField({
                    data: {
                      ...data,
                      description: data.description,
                    },
                  });
                }}
                onChange={(e) => {
                  setData({
                    ...data,
                    description: e.target.value,
                  });
                }}
              />
            </div>
          )}
        </div>

        <Button
          icon={<MinusCircleOutlined className="group-hover:text-error" />}
          type="text"
          className="group text-text-4 hover:text-error"
          style={{
            color: 'var(--text-4)',
          }}
          onClick={openConfirm(onDel)}
        />
      </div>
      <ConfirmModal />
    </>
  );
}
